﻿using System;
using System.Runtime.InteropServices;

namespace Microsoft.WowAddonStudio.FrameXml.Formats.Blp
{
    internal class NativeMethods
    {
        private const int SQUISH_DXT_UNC = 0 << 0;
        private const int SQUISH_DXT1 = 1 << 0;
        private const int SQUISH_DXT3 = 1 << 1;
        private const int SQUISH_DXT5 = 1 << 2;

        /// <summary>
        /// Decompresses a DXT image.
        /// </summary>
        /// <param name="width">The width of the image.</param>
        /// <param name="height">The height of the image.</param>
        /// <param name="data">The compressed data.</param>
        /// <param name="compression">The type of the DXT compression.</param>
        /// <returns>An <see cref="IntPtr"/> to the decompressed image data</returns>
        /// <remarks>
        /// The returned native pointer must be freed using <see cref="Marshal.FreeHGlobal"/>.
        /// </remarks>
        public static IntPtr DecompressImage(int width, int height, byte[] data, BlpCompression compression)
        {
            int flag;
            switch (compression)
            {
                case BlpCompression.DXT1:
                    flag = SQUISH_DXT1;
                    break;
                case BlpCompression.DXT3:
                    flag = SQUISH_DXT3;
                    break;
                case BlpCompression.DXT5:
                    flag = SQUISH_DXT5;
                    break;
                case BlpCompression.Uncompressed:
                    flag = SQUISH_DXT_UNC;
                    break;
                default:
                    throw new NotSupportedException();
            }

            // Allocate a native buffer for the image
            IntPtr buffer = Marshal.AllocHGlobal(width * height * 4);

            try
            {
                // Decompress the image
                NativeMethods.DecompressImage(buffer, width, height, data, flag);
            }
            catch
            {
                Marshal.FreeHGlobal(buffer);
                return IntPtr.Zero;
            }
            

            // Return the buffer
            return buffer;
        }

        [DllImport("Squish.dll", EntryPoint = "#1")]
        private static extern void DecompressImage(IntPtr targetBuffer, int width, int height, [MarshalAs(UnmanagedType.LPArray)]byte[] blocks, int flags);
    }
}